/******************************************************************************************
文件名：loice_slave_parser.h
作者：狼狼    版本：Loice    创建日期：2021.8.27
文件描述：
    头文件。
历史修改记录：
1. 2021-8-27:Loice 狼狼
创建。
2. 2022-5-11:Loice 狼狼
代码公开。
******************************************************************************************/
#ifndef LOICE_PARSER__
#define LOICE_PARSER__ // Loice主设备和从设备角色只能选择一个
//+------------------------------------------------------------------------------------------+
//|                                           头文件
//+------------------------------------------------------------------------------------------+
/*|*/#include <stdbool.h>
/*|*/#include <stdint.h>
/*|*/#include <unistd.h>
/*|*/#include <sys/time.h>
/*|*/#include <pthread.h>
/*|*/#include "tcp_comm.h"
/*|*/#include "internal_cmd.h"
/*|*/#include "internal_data.h"
/*|*/#include "loice_protocol_version_1.h"
//+------------------------------------------------------------------------------------------+
//|                                         参数宏定义
//+------------------------------------------------------------------------------------------+
//|    ----------------------------------------
//|    一个解析器实例能够管理的最大会话数量
//|    NOTE:当前实现中每个会话占有一个处理线程，
//|         因此此值需基于系统性能和限制综合考量。
//|    ----------------------------------------
/*|*/#define MAX_SESSION_NUM 1
//|    ----------------------------------------
//|    指令时效性检查开关
//|    NOTE:若开启此宏定义，则当消息序列号小于
//|         等于记录中最大值时，消息将被丢弃。
//|    ----------------------------------------
/*|*/#define ENABLE_SEQ_CHECK
//|    ----------------------------------------
//|    KAP机制开关
//|    NOTE:Loice从设备端为心跳包的接收/回应方，
//|         超时将主动关闭会话。
//|         Loice主设备的指令可充当心跳包。
//|    ----------------------------------------
/*|*/  #define ENABLE_KAP
//|    ----------------------------------------
//|    KAP超时时间（秒）
//|    ----------------------------------------
/*|*/#define KAP_TIMEOUT 8
//|
/*|*/#define PARSER_SUCCESS                    0x00000000
//|    ----------------------------------------
//|    错误码：非法的参数
//|    ----------------------------------------
/*|*/#define PARSER_ERROR_ILLEGAL_PARAM        0x90031001
//|    ----------------------------------------
//|    错误码：申请内存错误
//|    ----------------------------------------
/*|*/#define PARSER_ERROR_MALLOC               0x90031003
//|    ----------------------------------------
//|    错误码：线程创建失败
//|    ----------------------------------------
/*|*/#define PARSER_ERROR_THREAD               0x90031004
//|    ----------------------------------------
//|    错误码：当前解析器（会话）状态不支持此操作
//|    ----------------------------------------
/*|*/#define PARSER_ERROR_UNEXPECT_STATE       0x90032001
//|    ----------------------------------------
//|    错误码：待存入的数据长度超出合法范围
//|    ----------------------------------------
/*|*/#define PARSER_ERROR_UNEXPECT_DATA_LENGTH 0x90032002
//|    ----------------------------------------
//|    错误码：当前解析器会话列表已满
//|    ----------------------------------------
/*|*/#define PARSER_ERROR_SESSION_LIST_FULL    0x90033001
//|    ----------------------------------------
//|    错误码：当前解析器会话列表是空的
//|    ----------------------------------------
/*|*/#define PARSER_ERROR_SESSION_LIST_EMPTY   0x90033002
//|    ----------------------------------------
//|    错误码：会话已经被注册
//|    ----------------------------------------
/*|*/#define PARSER_ERROR_SESSION_REGISTERED   0x90033003
//|    ----------------------------------------
//|    错误码：协议不匹配
//|    ----------------------------------------
/*|*/#define PARSER_ERROR_PROTOCOL             0x90033004
//|    ----------------------------------------
//|    错误码：会话不存在
//|    ----------------------------------------
/*|*/#define PARSER_ERROR_SESSION_NON_EXISTENT 0x90033005
//|    ----------------------------------------
//|    错误码：会话操作失败
//|    ----------------------------------------
/*|*/#define PARSER_ERROR_OPERATION_FAIL       0x90033006
//|
//|    ----------------------------------------
//|    退出原因状态码：
//|    0.未退出(PARSER_SUCCESS)      0x00000000
//|    1.发送异常                    0x9003E001
//|    2.接收异常                    0x9003E002
//|    3.malloc失败                  0x9003E003
//|    ----------------------------------------
/*|*/#define PARSER_EXIT_STAT_TX_ERROR      0x9003E001
/*|*/#define PARSER_EXIT_STAT_RX_ERROR      0x9002E002
/*|*/#define PARSER_EXIT_STAT_MALLOC_ERROR  0x9002E003
//+------------------------------------------------------------------------------------------+
//|                                          数据类型
//+------------------------------------------------------------------------------------------+
//|    ----------------------------------------
//|    用于描述解析器使用的协议版本的枚举类型
//|    ----------------------------------------
/*|*/typedef enum parser_protocol_version
/*|*/{
/*|*/    PARSER_PROTOCOL_INIT = 0,
/*|*/    PARSER_PROTOCOL_1    = 1,
/*|*/}ENUM_PARSER_PROCOTOL_VERSION;
//|
//|    ----------------------------------------
//|    用于描述解析器会话状态的枚举类型
//|    NOTE:仅内部使用
//|    ----------------------------------------
/*|*/typedef enum parser_session_state
/*|*/{
/*|*/    PARSER_SESSION_STAT_INIT = 0,
/*|*/    PARSER_SESSION_STAT_STANDBY,
//|      ----------------------------------------
//|      指令解析线程所处的中间状态
//|      NOTE:基于此状态对异步传来的消息做处理。
//|      ----------------------------------------
/*|*/    PARSER_SESSION_STAT_GOTHEAD1,
/*|*/    PARSER_SESSION_STAT_GOTHEAD2,
/*|*/    PARSER_SESSION_STAT_GOTHEAD3,
/*|*/    PARSER_SESSION_STAT_GOTHEAD4,
/*|*/    PARSER_SESSION_STAT_GOTHEAD5,
/*|*/    PARSER_SESSION_STAT_GOTHEAD6,
/*|*/    PARSER_SESSION_STAT_GOTHEAD7,
/*|*/    PARSER_SESSION_STAT_GOTHEAD8,
/*|*/    PARSER_SESSION_STAT_HEAD_CHECK_PASS,
/*|*/    PARSER_SESSION_STAT_CMD_BODY_CHECK_PASS,
/*|*/    PARSER_SESSION_STAT_MSG_ID_CHECK_PASS,
/*|*/    PARSER_SESSION_STAT_MSG_SEQ_CHECK_PASS,
/*|*/    PARSER_SESSION_STAT_CMD_REG_CHECK_PASS,
/*|*/    PARSER_SESSION_STAT_CMD_VERIFY_PASS,
/*|*/    PARSER_SESSION_STAT_CMD_ACTION_CHECK_PASS,
//|      PARSER_SESSION_STAT_DATA_BODY_CHECK_PASS,
//|      
/*|*/    PARSER_SESSION_STAT_EXIT,    // 会话的处理线程因故退出，等待回收会话资源
/*|*/    PARSER_SESSION_STAT_END,     // 会话已停止处理
/*|*/}ENUM_PARSER_SESSION_STATE;
//|
//|    ----------------------------------------
//|    用于存储一个解析器会话对象必要信息的结构
//|    ----------------------------------------
/*|*/typedef struct parser_session
/*|*/{
//|      ----------------------------------------
//|      传输层连接实例
//|      ----------------------------------------
/*|*/    ST_TCP_COMM *ptcpcomm_obj;
//|      ----------------------------------------
//|      解析器会话状态
//|      ----------------------------------------
/*|*/    ENUM_PARSER_SESSION_STATE state;
//|      ----------------------------------------
//|      指令解析线程退出状态码
//|      ----------------------------------------
/*|*/    int exit_state;
//|      ----------------------------------------
//|      解析器会话指令解析线程
//|      ----------------------------------------
/*|*/    pthread_t tid;
//|      ----------------------------------------
//|      解析器会话处理实例线程运行许可
//|      NOTE:此标志位为处理线程循环判断标志。
//|      ----------------------------------------
/*|*/    bool flag_run;
//|      ----------------------------------------
//|      TX_BUF发送互斥锁
//|      ----------------------------------------
/*|*/    pthread_mutex_t tx_mutex;
//|      ----------------------------------------
//|      本地设备号
//|      NOTE:协议版本1中，设备号仅使用24字节，后
//|           4字节保留为00H。
//|      ----------------------------------------
/*|*/    uint8_t local_device_id[28];
//|      ----------------------------------------
//|      远端设备号
//|      NOTE:协议版本1中，设备号仅使用24字节，后
//|           4字节保留为00H。
//|      ----------------------------------------
/*|*/    uint8_t remote_device_id[28];
//|      ----------------------------------------
//|      历史消息的最大序列号
//|      NOTE:用于旧指令判断以防止指令乱序。
//|      ----------------------------------------
/*|*/    uint16_t max_msg_seq;
//|      ----------------------------------------
//|      最后一次KAP的时间
//|      NOTE:用于KAP超时判断。
//|      ----------------------------------------
/*|*/    struct timeval last_kap_time;
//|      ----------------------------------------
//|      CMD_ACTION指令运行状态
//|      ----------------------------------------
/*|*/    bool flag_is_CMD_ACTION_run;
/*|*/}ST_PARSER_SESSION;
//|
//|    ----------------------------------------
//|    用于描述解析器状态的枚举类型
//|    NOTE:仅内部使用
//|    ----------------------------------------
/*|*/typedef enum parser_state
/*|*/{
/*|*/    PARSER_STAT_INIT = 0,
/*|*/    PARSER_STAT_OK,
/*|*/    PARSER_STAT_TEMP,
/*|*/}ENUM_PARSER_STATE;
//|
//|    ----------------------------------------
//|    用于存储一个解析器对象必要信息的结构
//|    ----------------------------------------
/*|*/typedef struct parser
/*|*/{
//|      ----------------------------------------
//|      解析器状态
//|      ----------------------------------------
/*|*/    ENUM_PARSER_STATE state;
//|      ----------------------------------------
//|      当前解析器实例使用的协议版本
//|      ----------------------------------------
/*|*/    ENUM_PARSER_PROCOTOL_VERSION protocol_version;
//|      ----------------------------------------
//|      解析器管理线程
//|      ----------------------------------------
/*|*/    pthread_t manager_tid;
//|      ----------------------------------------
//|      解析器管理线程运行许可
//|      ----------------------------------------
/*|*/    bool flag_manager_run;
//|      ----------------------------------------
//|      本地设备号
//|      NOTE:协议版本1中，设备号仅使用24字节，后
//|           4字节保留为00H。
//|      ----------------------------------------
/*|*/    uint8_t local_device_id[28];
//|      ----------------------------------------
//|      会话列表
//|      ----------------------------------------
/*|*/    struct parser_session * session_list[MAX_SESSION_NUM];
//|      ----------------------------------------
//|      会话列表中存储的会话数量
//|      ----------------------------------------
/*|*/    uint32_t session_num;
//|      ----------------------------------------
//|      CMD_ACTION全局指令运行状态
//|      NOTE:用于判断系统对阻塞指令处理是否正处
//|           于忙状态。
//|      EXPLAIN:如果设定Action指令对系统的资源占
//|              用是各会话互斥的，就需要将其放在
//|              解析器实例而非会话实例中，会话实
//|              例使用指针指向该全局标志。
//|      EXPLAIN:在当前Demo中，各会话共享全局编码
//|              器，因此无需全局标志位。
//|      ----------------------------------------
//|      bool flag_is_CMD_ACTION_run;
//|      ----------------------------------------
//|      回调函数集
//|      NOTE:以下函数指针在初始化套接字对象时被
//|           赋值。
//|      ATTENTION:使用解析器对象成员函数指针前必
//|                须先对其进行初始化！
//|      ----------------------------------------
/*|*/    int (*add_session)          (struct parser * const parser_obj, ST_TCP_COMM * const ptcpcomm_obj);
/*|*/    int (*delete_session)       (struct parser * const parser_obj, ST_TCP_COMM **pptcpcomm_obj);
/*|*/    int (*pack_data)            (struct parser * const parser_obj, ST_INTERNAL_DATA *pinternal_data);
/*|*/    int (*clear_cmd_action_flag)(struct parser * const parser_obj, uint32_t session_id);
/*|*/}ST_PARSER;
//+------------------------------------------------------------------------------------------+

#ifdef __cplusplus
extern "C" {
#endif
//+------------------------------------------------------------------------------------------+
//|                                       函数/变量声明
//+------------------------------------------------------------------------------------------+
/*|*/int parser_create (ST_PARSER **ppparser_obj, ENUM_PARSER_PROCOTOL_VERSION version, const uint8_t *plocal_device_id);
/*|*/int parser_destroy(ST_PARSER **ppparser_obj);
//+------------------------------------------------------------------------------------------+
#ifdef __cplusplus
}
#endif /* End of __cplusplus*/

#endif /* End of #define LOICE_PARSER__ */
